package top.azusall.securitydemo.filter;

import com.alibaba.fastjson2.JSON;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import top.azusall.common.entity.R;
import top.azusall.securitydemo.common.MyUserDetail;
import top.azusall.securitydemo.thread.UserDetailThreadLocalUtil;
import top.azusall.securitydemo.util.JwtUtil;

import java.io.IOException;
import java.time.Instant;

/**
 * @author houmo
 */
@Slf4j
public class JwtFilter extends OncePerRequestFilter {



    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.info("JwtFilter doFilter");

        String token = request.getHeader("Token");
        // token 为空 或者 是登录接口 直接放行
        if (StringUtils.hasText(token) && !request.getRequestURI().startsWith("/login")) {
            // 校验jwt
            JwtUtil.Claim claim = JwtUtil.verifyJwt(token);
            MyUserDetail myUserDetail = claim.getMyUserDetail();

            //过期处理
            if (claim.getExp() < Instant.now().toEpochMilli()) {
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().println(JSON.toJSON(new R(HttpStatus.UNAUTHORIZED.value(), "token已过期!", null)));
                return;
            }

            // 到达刷新时间，刷新jwt
            if (JwtUtil.isRefresh(claim)) {
                String s = JwtUtil.generateJwt(myUserDetail);
                request.setAttribute("Set-Token", s);
                log.info("用户名：{} token已刷新：{}", myUserDetail.getUsername(), s);
            }

            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(myUserDetail.getUsername(), null, myUserDetail.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        }






        filterChain.doFilter(request, response);
        UserDetailThreadLocalUtil.remove();
    }


}
